package util

import (
	"archive/zip"
	"bufio"
	"bytes"
	"encoding/csv"
	"errors"
	"fmt"
	"github.com/xuri/excelize/v2"
	"html/template"
	"io"
	"os"
	"path"
	"path/filepath"
	"runtime"
	schemaSieve "sieve_admin_server_userpass/app/schema/sieve"
	"sieve_admin_server_userpass/lib/config"
	"sieve_admin_server_userpass/lib/util/convert"
	"sieve_admin_server_userpass/pkg/excel"
	"sieve_admin_server_userpass/pkg/util"
	"strconv"
	"strings"
	"time"
)

var (
	FileStorage = func(args ...interface{}) string {
		fileBase := filepath.Base(os.Args[0])
		if len(args) == 1 {
			fileBase = args[0].(string)
		}
		return *config.String("file.storage", fmt.Sprintf("/data/%v", fileBase), "file storage dir prefix")
	}
)

type argsParams struct {
	ExportKind int
	AgeMap     map[string]interface{}
	TableHtml  string
	AllFields  bool
}

func getArgsParams(args ...interface{}) argsParams {

	var ap = argsParams{
		AgeMap: make(map[string]interface{}),
	}
	if len(args) == 1 {
		ap.ExportKind = args[0].(int)
	}

	if len(args) == 2 {
		ap.ExportKind = args[0].(int)

		if args[1].(string) != "" {
			s := strings.Split(args[1].(string), "-")
			if len(s) == 1 {
				ap.AgeMap[s[0]] = struct{}{}
			}
			if len(s) == 2 {
				for i := convert.Atoi(s[0]); i <= convert.Atoi(s[1]); i++ {
					ap.AgeMap[strconv.Itoa(i)] = struct{}{}
				}
			}
		}
	}

	if len(args) == 3 {

		ap.ExportKind = args[0].(int)
		if args[1].(string) != "" {
			s := strings.Split(args[1].(string), "-")
			if len(s) == 1 {
				ap.AgeMap[s[0]] = struct{}{}
			}
			if len(s) == 2 {
				for i := convert.Atoi(s[0]); i <= convert.Atoi(s[1]); i++ {
					ap.AgeMap[strconv.Itoa(i)] = struct{}{}
				}
			}
		}

		ap.TableHtml = args[2].(string)
	}

	if len(args) == 4 {
		ap.ExportKind = args[0].(int)
		if args[1].(string) != "" {
			s := strings.Split(args[1].(string), "-")
			if len(s) == 1 {
				ap.AgeMap[s[0]] = struct{}{}
			}
			if len(s) == 2 {
				for i := convert.Atoi(s[0]); i <= convert.Atoi(s[1]); i++ {
					ap.AgeMap[strconv.Itoa(i)] = struct{}{}
				}
			}
		}

		ap.TableHtml = args[2].(string)
		ap.AllFields = args[3].(bool)
	}

	return ap
}

func GetFilePath(d string, args ...interface{}) string {

	var isPath bool
	if len(args) == 1 {
		isPath = args[0].(bool)
	}

	dir, fileName := path.Dir(d), filepath.Base(d)
	if runtime.GOOS == "windows" {

		g, _ := os.Getwd()
		if len(args) == 2 {
			g = args[1].(string)
		}
		dir = path.Clean(g + string(os.PathSeparator) + dir)
	}

	_ = os.MkdirAll(dir, os.ModePerm)
	if isPath {
		return dir
	}
	return path.Clean(dir + string(os.PathSeparator) + fileName)
}

func MergeFiles(outputPath string, inputPaths []string, ff func(fName string) string) error {
	outputFile, err := os.Create(outputPath)
	if err != nil {
		return err
	}
	defer func() {
		_ = outputFile.Close()
	}()

	for _, inputPath := range inputPaths {
		inputFile, err := os.Open(ff(inputPath))
		if err != nil {
			if inputFile != nil {
				inputFile.Close()
			}
			continue
			// return err
		}

		_, err = io.Copy(outputFile, inputFile)
		_ = inputFile.Close() // 关闭输入文件
		if err != nil {
			return err
		}
	}

	if err != nil {
		return err
	}

	return nil
}

func CreateZipFile(zipPath string, fileList []string, ff func(fName string) string, fCallBack func(fName string)) error {

	if len(fileList) < 1 {
		return fmt.Errorf("file list is empty")
	}
	var opContinue bool
	if len(fileList) > 1 {
		opContinue = true
	}

	fz, err := os.Create(zipPath)
	if err != nil {
		return err
	}

	zw := zip.NewWriter(fz)

	defer func() {
		_ = zw.Close()
		_ = fz.Close()
		if fCallBack != nil {
			fCallBack(fz.Name())
		}
		// _ = os.Remove(fz.Name())
	}()

	for _, fileName := range fileList {
		fr, err := os.Open(ff(fileName))
		if err != nil {
			if opContinue {
				continue
			}
			return err
		}

		stat, _ := fr.Stat()
		if stat.IsDir() {
			if opContinue {
				continue
			}
			return errors.New("only support package for files")
		}

		// 写入文件的头信息
		var w io.Writer
		w, err = zw.Create(filepath.Base(fileName))

		if err != nil {
			if opContinue {
				continue
			}
			return err
		}

		// 写入文件内容
		_, err = io.Copy(w, fr)
		if err != nil {
			if opContinue {
				continue
			}
			return err
		}
	}
	return zw.Flush()
}

/*
ty 指定分割的小文件的文件格式
1: txt
2: csv
*/
func TxtFileSplitToTxt(fileName string, npf int, args ...interface{}) ([]string, error) {

	f, err := os.Open(fileName)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	reader := bufio.NewReader(f)

	var (
		baseFile = filepath.Base(fileName)
		index    = 1
		count    = 1
		files    []string
		ss       = strings.Split(baseFile, ".")
		ff       = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v", ss[0], index))
	)

	if len(ss) == 2 {
		ff = ff + fmt.Sprintf(".%v", ss[len(ss)-1])
	}

	fWriter, err := os.Create(ff)
	if err != nil {
		return nil, err
	}
	rWriter := bufio.NewWriter(fWriter)

	var hasExtraFile = true
	for {
		line, _, err := reader.ReadLine()
		if err == io.EOF {
			break
		}

		_, _ = rWriter.WriteString(fmt.Sprintf("%v%c%c", string(line), 0x0D, 0x0A))
		if count >= npf && npf != 0 {
			files = append(files, ff)
			_ = rWriter.Flush()
			count = 1
			_ = fWriter.Close()

			if reader.Buffered() <= 0 {
				hasExtraFile = false
				break
			}

			index = index + 1
			// ff = fmt.Sprintf("%v_%v", ss[0], index)
			ff = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v", ss[0], index))
			if len(ss) == 2 {
				ff = ff + fmt.Sprintf(".%v", ss[len(ss)-1])
			}
			fWriter, err = os.Create(ff)
			if err != nil {
				fmt.Println(err)
			}
			rWriter = bufio.NewWriter(fWriter)
			continue
		}
		count = count + 1
	}

	if hasExtraFile {
		files = append(files, ff)
		_ = rWriter.Flush()
		_ = fWriter.Close()
	}
	return files, nil
}

func CSVFileSplitToTxt(fileName string, npf int, args ...interface{}) ([]string, error) {

	f, err := os.Open(fileName)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	reader := csv.NewReader(f)
	fInfo, _ := f.Stat()
	totalSize := fInfo.Size()

	var (
		baseFile  = filepath.Base(fileName)
		index     = 1
		count     = 1
		i         = 1
		files     []string
		ss        = strings.Split(baseFile, ".")
		ff        = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v.txt", ss[0], index))
		allFields bool
	)

	// if len(args) == 3 {
	//	allFields = args[2].(bool)
	// }

	allFields = getArgsParams(args...).AllFields

	fWriter, err := os.Create(ff)
	if err != nil {
		return nil, err
	}
	rWriter := bufio.NewWriter(fWriter)

	var hasExtraFile = true
	for {
		line, err := reader.Read()
		if err == io.EOF {
			break
		}

		if i == 1 {
			i = i + 1
			continue
		}

		data := line[0]
		if allFields {
			strings.Join(line, ",")
		}
		_, _ = rWriter.WriteString(fmt.Sprintf("%v%c%c", data, 0x0D, 0x0A))
		if count >= npf && npf != 0 {
			files = append(files, ff)
			_ = rWriter.Flush()
			count = 1
			_ = fWriter.Close()

			if reader.InputOffset() >= totalSize {
				hasExtraFile = false
				break
			}

			index = index + 1
			ff = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v.txt", ss[0], index))
			fWriter, err = os.Create(ff)
			if err != nil {
				continue
			}
			rWriter = bufio.NewWriter(fWriter)
			continue
		}
		count = count + 1
	}

	if hasExtraFile {
		files = append(files, ff)
		_ = rWriter.Flush()
		_ = fWriter.Close()
	}
	return files, nil
}

func CSVFileSplitToCSV(fileName string, npf int, args ...interface{}) ([]string, error) {

	var (
		ap         = getArgsParams(args...)
		exportKind = ap.ExportKind
		ageMap     = ap.AgeMap
	)

	f, err := os.Open(fileName)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	reader := csv.NewReader(f)

	fInfo, _ := f.Stat()
	totalSize := fInfo.Size()

	var (
		baseFile = filepath.Base(fileName)
		index    = 1
		count    = 1
		files    []string
		ss       = strings.Split(baseFile, ".")
		ff       = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v.csv", ss[0], index))
	)

	fWriter, err := os.Create(ff)
	if err != nil {
		return nil, err
	}
	rWriter := csv.NewWriter(fWriter)

	var (
		rowIndex     = 0
		hasExtraFile = true
		colName      []string
	)

	for {

		row, err := reader.Read()
		if err == io.EOF {
			break
		}

		rowIndex = rowIndex + 1

		// 读取列名称
		if rowIndex == 1 {
			colName = row
			continue
		}

		// 转换为结构体
		var (
			kv = make(map[string]interface{})
			v  = schemaSieve.SieveSexExportType{}
		)

		for i, key := range colName {
			if i >= len(row) {
				kv[key] = ""
				continue
			}
			kv[key] = row[i]
			if key == "day" {
				if v, ok := kv["time"]; ok {
					if t, err := time.Parse("2006-01-02 15:04:05", v.(string)); err == nil {
						row[i] = strconv.Itoa(int(time.Now().Sub(t).Hours() / 24))
					}
				}
			}
		}

		util.Map2Struct(kv, "json", &v)

		if exportKind == 1 && v.Sex != "male" {
			continue
		}

		if exportKind == 2 && v.Sex != "female" {
			continue
		}

		if exportKind == 4 && (v.Sex != "female" && v.Sex != "male") {
			continue
		}

		if _, ok := ageMap[v.Age]; !ok && len(ageMap) > 0 && (exportKind == 1 || exportKind == 2 || exportKind == 4) {
			continue
		}

		if count == 1 {
			_ = rWriter.Write(colName)
		}

		_ = rWriter.Write(row)
		if count >= npf && npf != 0 {

			files = append(files, ff)
			rWriter.Flush()
			count = 1
			_ = fWriter.Close()

			if reader.InputOffset() >= totalSize {
				hasExtraFile = false
				break
			}

			index = index + 1
			ff = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v.csv", ss[0], index))

			fWriter, err = os.Create(ff)
			if err != nil {
				continue
			}
			rWriter = csv.NewWriter(fWriter)
			continue
		}
		count = count + 1
	}

	if hasExtraFile {
		files = append(files, ff)
		rWriter.Flush()
		_ = fWriter.Close()
	}
	return files, nil
}
func TxtFileSplitToCSV(fileName string, npf int, args ...interface{}) ([]string, error) {

	f, err := os.Open(fileName)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	reader := bufio.NewReader(f)

	var (
		baseFile = filepath.Base(fileName)
		index    = 1
		count    = 1
		files    []string
		ss       = strings.Split(baseFile, ".")
		ff       = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v.csv", ss[0], index))
	)

	fWriter, err := os.Create(ff)
	if err != nil {
		return nil, err
	}
	rWriter := csv.NewWriter(fWriter)

	var hasExtraFile = true
	for {
		line, _, err := reader.ReadLine()
		if err == io.EOF {
			break
		}

		_ = rWriter.Write([]string{fmt.Sprintf("\t%v", string(line))})
		if count >= npf && npf != 0 {
			files = append(files, ff)
			rWriter.Flush()
			count = 1
			_ = fWriter.Close()

			if reader.Buffered() <= 0 {
				hasExtraFile = false
				break
			}

			index = index + 1
			ff = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v.csv", ss[0], index))

			fWriter, err = os.Create(ff)
			if err != nil {
				fmt.Println(err)
			}
			rWriter = csv.NewWriter(fWriter)
			continue
		}
		count = count + 1
	}
	if hasExtraFile {
		files = append(files, ff)
		rWriter.Flush()
		_ = fWriter.Close()
	}
	return files, nil
}

func ExcelFileSplitToCSV(fileName string, npf int, args ...interface{}) ([]string, error) {

	var (
		deDupSieve  []schemaSieve.SieveSexExportType
		deDupSieveR []schemaSieve.SieveSexExportType
		exportKind  int
		ageMap      = make(map[string]struct{})
	)

	if len(args) == 1 {
		exportKind = args[0].(int)
	}
	if len(args) == 2 {
		exportKind = args[0].(int)

		if args[1].(string) != "" {
			s := strings.Split(args[1].(string), "-")
			if len(s) == 1 {
				ageMap[s[0]] = struct{}{}
			}
			if len(s) == 2 {
				for i := convert.Atoi(s[0]); i <= convert.Atoi(s[1]); i++ {
					ageMap[strconv.Itoa(i)] = struct{}{}
				}
			}
		}
	}

	if err := (excel.Sheet{Filename: fileName, Sheet: "Sheet1"}).Scan(&deDupSieve); err != nil {
		return nil, err
	}

	var (
		baseFile = filepath.Base(fileName)
		index    = 1
		count    = 1
		files    []string
		ss       = strings.Split(baseFile, ".")
		ff       = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v.xlsx", ss[0], index))
	)

	for i, v := range deDupSieve {

		if exportKind == 1 && v.Sex != "male" {
			continue
		}

		if exportKind == 2 && v.Sex != "female" {
			continue
		}

		if exportKind == 4 && (v.Sex != "female" && v.Sex != "male") {
			continue
		}

		if _, ok := ageMap[v.Age]; !ok && len(ageMap) > 0 && (exportKind == 1 || exportKind == 2 || exportKind == 4) {
			continue
		}

		deDupSieveR = append(deDupSieveR, v)
		if count >= npf && npf != 0 {
			files = append(files, ff)
			count = 1
			buff, _ := (&excel.Sheet{Sheet: "Sheet1"}).Export(&deDupSieveR)
			_ = os.WriteFile(ff, buff.Bytes(), 0644)
			deDupSieveR = deDupSieveR[:0]
			if i+1 >= len(deDupSieve) {
				break
			}
			index = index + 1
			ff = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v.xlsx", ss[0], index))
			continue
		}
		count = count + 1
	}

	if len(deDupSieveR) > 0 {
		buff, _ := (&excel.Sheet{Sheet: "Sheet1"}).Export(&deDupSieveR)
		_ = os.WriteFile(ff, buff.Bytes(), 0644)
		files = append(files, ff)
	}
	return files, nil
}

func SexCSVFileSplitToHtml(fileName string, npf int, args ...interface{}) ([]string, error) {

	var (
		ap         = getArgsParams(args...)
		exportKind = ap.ExportKind
		ageMap     = ap.AgeMap
		tableHtml  = ap.TableHtml
	)

	f, err := os.Open(fileName)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	reader := csv.NewReader(f)

	fInfo, _ := f.Stat()
	totalSize := fInfo.Size()

	var (
		deDupSieveR []schemaSieve.SieveSexExportType
		templ       = template.Must(template.New("").Parse(tableHtml))
		baseFile    = filepath.Base(fileName)
		index       = 1
		count       = 1
		files       []string
		ss          = strings.Split(baseFile, ".")
		ff          = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v.html", ss[0], index))
	)

	fWriter, err := os.Create(ff)
	if err != nil {
		return nil, err
	}

	var (
		rowIndex = 0
		colName  []string
	)

	for {

		row, err := reader.Read()
		if err == io.EOF {
			break
		}

		rowIndex = rowIndex + 1

		// 读取列名称
		if rowIndex == 1 {
			colName = row
			continue
		}

		// 转换为结构体
		var (
			kv = make(map[string]interface{})
			v  = schemaSieve.SieveSexExportType{}
		)

		for i, key := range colName {
			if i >= len(row) {
				kv[key] = ""
				continue
			}
			kv[key] = row[i]
		}

		util.Map2Struct(kv, "json", &v)

		if exportKind == 1 && v.Sex != "male" {
			continue
		}

		if exportKind == 2 && v.Sex != "female" {
			continue
		}

		if exportKind == 4 && (v.Sex != "female" && v.Sex != "male") {
			continue
		}

		if _, ok := ageMap[v.Age]; !ok && len(ageMap) > 0 && (exportKind == 1 || exportKind == 2 || exportKind == 4) {
			continue
		}

		deDupSieveR = append(deDupSieveR, v)
		if count >= npf && npf != 0 {

			files = append(files, ff)
			count = 1

			_ = templ.Execute(fWriter, deDupSieveR)
			deDupSieveR = deDupSieveR[:0]
			if reader.InputOffset() >= totalSize {
				break
			}
			index = index + 1
			ff = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v.html", ss[0], index))

			fWriter, _ = os.Create(ff)
			continue
		}
		count = count + 1
	}

	if len(deDupSieveR) > 0 {
		_ = templ.Execute(fWriter, deDupSieveR)

		_ = fWriter.Close()
		files = append(files, ff)
	}
	return files, nil
}

func SexExcelFileSplitToHtml(fileName string, npf int, args ...interface{}) ([]string, error) {

	var (
		deDupSieve  []schemaSieve.SieveSexExportType
		deDupSieveR []schemaSieve.SieveSexExportType
		ap          = getArgsParams(args...)
		exportKind  = ap.ExportKind
		ageMap      = ap.AgeMap
		tableHtml   = ap.TableHtml
	)

	if err := (excel.Sheet{Filename: fileName, Sheet: "Sheet1"}).Scan(&deDupSieve); err != nil {
		return nil, err
	}

	var (
		templ    = template.Must(template.New("").Parse(tableHtml))
		baseFile = filepath.Base(fileName)
		index    = 1
		count    = 1
		files    []string
		ss       = strings.Split(baseFile, ".")
		ff       = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v.html", ss[0], index))
	)

	fWriter, err := os.Create(ff)
	if err != nil {
		return nil, err
	}

	for i, v := range deDupSieve {

		if exportKind == 1 && v.Sex != "male" {
			continue
		}

		if exportKind == 2 && v.Sex != "female" {
			continue
		}

		if exportKind == 4 && (v.Sex != "female" && v.Sex != "male") {
			continue
		}

		if _, ok := ageMap[v.Age]; !ok && len(ageMap) > 0 && (exportKind == 1 || exportKind == 2 || exportKind == 4) {
			continue
		}

		deDupSieveR = append(deDupSieveR, v)
		if count >= npf && npf != 0 {
			files = append(files, ff)
			count = 1

			_ = templ.Execute(fWriter, deDupSieveR)
			deDupSieveR = deDupSieveR[:0]
			if i+1 >= len(deDupSieve) {
				break
			}
			index = index + 1
			ff = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v.html", ss[0], index))

			fWriter, _ = os.Create(ff)
			continue
		}
		count = count + 1
	}

	if len(deDupSieveR) > 0 {
		_ = templ.Execute(fWriter, deDupSieveR)

		_ = fWriter.Close()
		files = append(files, ff)
	}
	return files, nil
}

// 只读取第一列的号码，写入到txt文件中
func ExcelFileSplitToTxt(fileName string, npf int, args ...interface{}) ([]string, error) {

	var (
		deDupSieve  []schemaSieve.XlsxOnlyMobileType
		deDupSieveR []string
	)

	if err := (excel.Sheet{Filename: fileName, Sheet: "Sheet1"}).Scan(&deDupSieve); err != nil {
		return nil, err
	}

	var (
		baseFile = filepath.Base(fileName)
		index    = 1
		count    = 1
		files    []string
		ss       = strings.Split(baseFile, ".")
		ff       = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v.txt", ss[0], index))
	)

	for i, v := range deDupSieve {

		data := fmt.Sprintf("%v", v.Mobile)

		deDupSieveR = append(deDupSieveR, data)
		if count >= npf && npf != 0 {
			files = append(files, ff)
			count = 1
			buff := &bytes.Buffer{}
			buff.WriteString(strings.Join(deDupSieveR, fmt.Sprintf("%c%c", 0x0D, 0x0A)))
			_ = os.WriteFile(ff, buff.Bytes(), 0644)
			deDupSieveR = deDupSieveR[:0]
			if i+1 >= len(deDupSieve) {
				break
			}
			index = index + 1
			ff = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v.txt", ss[0], index))
			continue
		}
		count = count + 1
	}

	if len(deDupSieveR) > 0 {
		buff := &bytes.Buffer{}
		buff.WriteString(strings.Join(deDupSieveR, fmt.Sprintf("%c%c", 0x0D, 0x0A)))
		_ = os.WriteFile(ff, buff.Bytes(), 0644)
		files = append(files, ff)
	}
	return files, nil
}

func SexExcelFileSplitToExcel(fileName string, npf int, args ...interface{}) ([]string, error) {

	var (
		deDupSieve  []schemaSieve.SieveSexExportType
		deDupSieveR []schemaSieve.SieveSexExportType
		ap          = getArgsParams(args...)
		exportKind  = ap.ExportKind
		ageMap      = ap.AgeMap
	)

	if err := (excel.Sheet{Filename: fileName, Sheet: "Sheet1"}).Scan(&deDupSieve); err != nil {
		return nil, err
	}

	var (
		baseFile    = filepath.Base(fileName)
		index       = 1
		filerSchema = excel.Schema{}
		count       = 1
		files       []string
		ss          = strings.Split(baseFile, ".")
		ff          = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v.xlsx", ss[0], index))
	)

	maxColumnIndex := 1
	dayEnable := false
	for i, v := range deDupSieve {

		timeIndex := 0
		if exportKind == 1 && v.Sex != "male" {
			continue
		}

		if exportKind == 2 && v.Sex != "female" {
			continue
		}

		if exportKind == 4 && (v.Sex != "female" && v.Sex != "male") {
			continue
		}

		if _, ok := ageMap[v.Age]; !ok && len(ageMap) > 0 && (exportKind == 1 || exportKind == 2 || exportKind == 4) {
			continue
		}

		if v.Mobile != "" {
			timeIndex = timeIndex + 1
			filerSchema["mobile"] = true
		}
		if v.WhatsMobile != "" {
			timeIndex = timeIndex + 1
			filerSchema["whats_mobile"] = true
		}

		if v.Number != "" {
			timeIndex = timeIndex + 1
			filerSchema["number"] = true
		}
		if v.NickName2 != "" {
			timeIndex = timeIndex + 1
			filerSchema["nickName"] = true
		}
		if v.Sex != "" {
			timeIndex = timeIndex + 1
			filerSchema["sex"] = true
		}
		if v.Age != "" {
			timeIndex = timeIndex + 1
			filerSchema["age"] = true
		}
		if v.Picture != "" {
			timeIndex = timeIndex + 1
			filerSchema["pic"] = true
		}
		if v.UserName != "" {
			timeIndex = timeIndex + 1
			filerSchema["userName"] = true
		}
		if v.UID != "" {
			timeIndex = timeIndex + 1
			filerSchema["uid"] = true
		}
		if v.NickName != "" {
			timeIndex = timeIndex + 1
			filerSchema["nickname"] = true
		}
		if v.Valid != "" {
			timeIndex = timeIndex + 1
			filerSchema["valid"] = true
		}
		if v.Time != "" {
			timeIndex = timeIndex + 1
			filerSchema["time"] = true
		}

		if v.Day != "" {
			timeIndex = timeIndex + 1
			filerSchema["day"] = true
			if timeIndex >= maxColumnIndex {
				maxColumnIndex = timeIndex
			}
			dayEnable = true
		}

		deDupSieveR = append(deDupSieveR, v)
		if count >= npf && npf != 0 {
			if dayEnable {
				for i := range deDupSieveR {
					deDupSieveR[i].Day = fmt.Sprintf("=DAYS(NOW(),%c%v)", int('A')+(maxColumnIndex-2), i+2)
					if _, err := time.Parse("2006-01-02 15:04:05", deDupSieveR[i].Time); err != nil {
						deDupSieveR[i].Day = ""
					}
				}
				maxColumnIndex = 1
				dayEnable = false
			}
			files = append(files, ff)
			count = 1
			buff, _ := (&excel.Sheet{Sheet: "Sheet1"}).Filter(filerSchema).Export(&deDupSieveR)
			_ = os.WriteFile(ff, buff.Bytes(), 0644)
			deDupSieveR = deDupSieveR[:0]
			if i+1 >= len(deDupSieve) {
				break
			}
			index = index + 1
			ff = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v.xlsx", ss[0], index))
			continue
		}
		count = count + 1
	}

	if len(deDupSieveR) > 0 {

		if dayEnable {
			for i := range deDupSieveR {
				deDupSieveR[i].Day = fmt.Sprintf("=DAYS(NOW(),%c%v)", int('A')+(maxColumnIndex-2), i+2)
				if _, err := time.Parse("2006-01-02 15:04:05", deDupSieveR[i].Time); err != nil {
					deDupSieveR[i].Day = ""
				}
			}
		}

		buff, _ := (&excel.Sheet{Sheet: "Sheet1"}).Filter(filerSchema).Export(&deDupSieveR)
		_ = os.WriteFile(ff, buff.Bytes(), 0644)
		files = append(files, ff)
	}
	return files, nil
}

func SexExcelFileSplitToExcel2(fileName string, npf int, args ...interface{}) ([]string, error) {

	var (
		deDupSieveR []schemaSieve.SieveSexExportType
		exportKind  int
		ageMap      = make(map[string]struct{})
	)

	if len(args) == 1 {
		exportKind = args[0].(int)
	}
	if len(args) == 2 {
		exportKind = args[0].(int)

		if args[1].(string) != "" {
			s := strings.Split(args[1].(string), "-")
			if len(s) == 1 {
				ageMap[s[0]] = struct{}{}
			}
			if len(s) == 2 {
				for i := convert.Atoi(s[0]); i <= convert.Atoi(s[1]); i++ {
					ageMap[strconv.Itoa(i)] = struct{}{}
				}
			}
		}
	}

	f, err := excelize.OpenFile(fileName)
	if err != nil {
		return nil, err
	}
	defer func() {
		if f != nil {
			_ = f.Close()
		}
	}()

	var (
		baseFile       = filepath.Base(fileName)
		index          = 1
		count          = 1
		filerSchema    = excel.Schema{}
		files          []string
		ss             = strings.Split(baseFile, ".")
		ff             = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v.xlsx", ss[0], index))
		maxColumnIndex = 1
		dayEnable      = false
	)

	fmt.Println("时间3：", time.Now())
	// rows, err := f.GetRows("Sheet1")
	rows, err := f.Rows("Sheet1")
	if err != nil {
		return nil, err
	}

	var (
		rowIndex = 0
		colName  []string
	)
	fmt.Println("时间1：", time.Now())

	for rows.Next() {

		rows.GetRowOpts()
		fmt.Println("时间7：", time.Now())
		row, err := rows.Columns()
		if err != nil {
			break
		}
		fmt.Println("时间8：", time.Now())

		rowIndex = rowIndex + 1

		// 读取列名称
		if rowIndex == 1 {
			colName = row
			continue
		}

		// 转换为结构体
		var (
			kv = make(map[string]interface{})
			v  = schemaSieve.SieveSexExportType{}
		)

		for i, key := range colName {
			if i >= len(row) {
				kv[key] = ""
				continue
			}
			kv[key] = row[i]
		}

		util.Map2Struct(kv, "json", &v)

		timeIndex := 0
		if exportKind == 1 && v.Sex != "male" {
			continue
		}

		if exportKind == 2 && v.Sex != "female" {
			continue
		}

		if exportKind == 4 && (v.Sex != "female" && v.Sex != "male") {
			continue
		}

		if _, ok := ageMap[v.Age]; !ok && len(ageMap) > 0 && (exportKind == 1 || exportKind == 2 || exportKind == 4) {
			continue
		}

		if v.Mobile != "" {
			timeIndex = timeIndex + 1
			filerSchema["mobile"] = true
		}
		if v.WhatsMobile != "" {
			timeIndex = timeIndex + 1
			filerSchema["whats_mobile"] = true
		}

		if v.Number != "" {
			timeIndex = timeIndex + 1
			filerSchema["number"] = true
		}
		if v.NickName2 != "" {
			timeIndex = timeIndex + 1
			filerSchema["nickName"] = true
		}
		if v.Sex != "" {
			timeIndex = timeIndex + 1
			filerSchema["sex"] = true
		}
		if v.Age != "" {
			timeIndex = timeIndex + 1
			filerSchema["age"] = true
		}
		if v.Picture != "" {
			timeIndex = timeIndex + 1
			filerSchema["pic"] = true
		}
		if v.UserName != "" {
			timeIndex = timeIndex + 1
			filerSchema["userName"] = true
		}
		if v.UID != "" {
			timeIndex = timeIndex + 1
			filerSchema["uid"] = true
		}
		if v.NickName != "" {
			timeIndex = timeIndex + 1
			filerSchema["nickname"] = true
		}
		if v.Valid != "" {
			timeIndex = timeIndex + 1
			filerSchema["valid"] = true
		}
		if v.Time != "" {
			timeIndex = timeIndex + 1
			filerSchema["time"] = true
		}

		if v.Day != "" {
			timeIndex = timeIndex + 1
			filerSchema["day"] = true
			if timeIndex >= maxColumnIndex {
				maxColumnIndex = timeIndex
			}
			dayEnable = true
		}

		deDupSieveR = append(deDupSieveR, v)
		if count >= npf && npf != 0 {
			if dayEnable {
				for i := range deDupSieveR {
					deDupSieveR[i].Day = fmt.Sprintf("=DAYS(NOW(),%c%v)", int('A')+(maxColumnIndex-2), i+2)
					if _, err := time.Parse("2006-01-02 15:04:05", deDupSieveR[i].Time); err != nil {
						deDupSieveR[i].Day = ""
					}
				}
				maxColumnIndex = 1
				dayEnable = false
			}

			files = append(files, ff)
			count = 1
			buff, _ := (&excel.Sheet{Sheet: "Sheet1"}).Filter(filerSchema).Export(&deDupSieveR)
			_ = os.WriteFile(ff, buff.Bytes(), 0644)
			deDupSieveR = deDupSieveR[:0]
			// if rowIndex+1 >= len(deDupSieve) {
			//	break
			// }
			index = index + 1
			ff = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v.xlsx", ss[0], index))
			continue
		}

		count = count + 1
	}

	fmt.Println("时间2：", time.Now())
	if len(deDupSieveR) > 0 {

		if dayEnable {
			for i := range deDupSieveR {
				deDupSieveR[i].Day = fmt.Sprintf("=DAYS(NOW(),%c%v)", int('A')+(maxColumnIndex-2), i+2)
				if _, err := time.Parse("2006-01-02 15:04:05", deDupSieveR[i].Time); err != nil {
					deDupSieveR[i].Day = ""
				}
			}
		}

		buff, _ := (&excel.Sheet{Sheet: "Sheet1"}).Filter(filerSchema).Export(&deDupSieveR)
		_ = os.WriteFile(ff, buff.Bytes(), 0644)
		files = append(files, ff)
	}

	fmt.Println("时间4：", time.Now())
	return files, nil
}

// 运营商数据格式导出
func OperatorExcelFileSplitToExcel(fileName string, npf int, args ...interface{}) ([]string, error) {

	var (
		filerSchema excel.Schema
		deDupSieve  []schemaSieve.OperatorSieveSexExportType
		deDupSieveR []schemaSieve.OperatorSieveSexExportType
	)

	if err := (excel.Sheet{Filename: fileName, Sheet: "Sheet1"}).Scan(&deDupSieve); err != nil {
		return nil, err
	}

	var (
		baseFile = filepath.Base(fileName)
		index    = 1
		count    = 1
		files    []string
		ss       = strings.Split(baseFile, ".")
		ff       = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v.xlsx", ss[0], index))
	)

	for i, v := range deDupSieve {

		if v.Number != "" {
			filerSchema["number"] = true
		}

		if v.CarrierId != "" {
			filerSchema["carrierId"] = true
		}
		if v.CarrierName != "" {
			filerSchema["carrierName"] = true
		}
		if v.CarrierMnc != "" {
			filerSchema["carrierMnc"] = true
		}
		if v.Validity != "" {
			filerSchema["validity"] = true
		}
		if v.NumberType != "" {
			filerSchema["numberType"] = true
		}

		if v.CountryCode != "" {
			filerSchema["countryCode"] = true
		}

		if v.CountryName != "" {
			filerSchema["countryName"] = true
		}

		if v.LastKnownEvent != "" {
			filerSchema["lastKnownEvent"] = true
		}

		if v.DisconnectDate != "" {
			filerSchema["disconnectDate"] = true
		}
		if v.ProvinceCode != "" {
			filerSchema["provinceCode"] = true
		}

		deDupSieveR = append(deDupSieveR, v)
		if count >= npf && npf != 0 {
			files = append(files, ff)
			count = 1
			buff, _ := (&excel.Sheet{Sheet: "Sheet1"}).Filter(filerSchema).Export(&deDupSieveR)
			_ = os.WriteFile(ff, buff.Bytes(), 0644)
			deDupSieveR = deDupSieveR[:0]
			if i+1 >= len(deDupSieve) {
				break
			}
			index = index + 1
			ff = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v.xlsx", ss[0], index))
			continue
		}
		count = count + 1
	}

	if len(deDupSieveR) > 0 {
		buff, _ := (&excel.Sheet{Sheet: "Sheet1"}).Filter(filerSchema).Export(&deDupSieveR)
		_ = os.WriteFile(ff, buff.Bytes(), 0644)
		files = append(files, ff)
	}
	return files, nil
}

// 运营商数据格式导出
func OperatorExcelFileSplitToTxt(fileName string, npf int, args ...interface{}) ([]string, error) {

	var (
		deDupSieve  []schemaSieve.OperatorSieveSexExportType
		deDupSieveR []string
	)

	if err := (excel.Sheet{Filename: fileName, Sheet: "Sheet1"}).Scan(&deDupSieve); err != nil {
		return nil, err
	}

	var (
		baseFile = filepath.Base(fileName)
		index    = 1
		count    = 1
		files    []string
		ss       = strings.Split(baseFile, ".")
		ff       = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v.txt", ss[0], index))
	)

	for i, v := range deDupSieve {

		data := fmt.Sprintf("%v:%v:%v:%v:%v:%v:%v:%v:%v:%v:%v", v.Number, v.CarrierId, v.CarrierName, v.CarrierMnc,
			v.Validity, v.NumberType, v.CountryCode, v.CountryName,
			v.LastKnownEvent, v.DisconnectDate, v.ProvinceCode)

		deDupSieveR = append(deDupSieveR, data)
		if count >= npf && npf != 0 {
			files = append(files, ff)
			count = 1
			buff := &bytes.Buffer{}
			buff.WriteString(strings.Join(deDupSieveR, fmt.Sprintf("%c%c", 0x0D, 0x0A)))
			_ = os.WriteFile(ff, buff.Bytes(), 0644)
			deDupSieveR = deDupSieveR[:0]
			if i+1 >= len(deDupSieve) {
				break
			}
			index = index + 1
			ff = filepath.Join(filepath.Dir(fileName), fmt.Sprintf("%v_%v.txt", ss[0], index))
			continue
		}
		count = count + 1
	}

	if len(deDupSieveR) > 0 {
		buff := &bytes.Buffer{}
		buff.WriteString(strings.Join(deDupSieveR, fmt.Sprintf("%c%c", 0x0D, 0x0A)))
		_ = os.WriteFile(ff, buff.Bytes(), 0644)
		files = append(files, ff)
	}
	return files, nil
}
